import Taro from '@tarojs/taro'
import crypto from 'crypto'
import * as zlib from 'zlib';


const returnObj = {
  navigateBack: (delta = 1, duration = 1500) => {
    setTimeout(() => {
      Taro.navigateBack({
        delta: delta
      })
    }, duration);
  },
  reLaunch: (url = '/pages/index/index', duration = 1500) => {
    setTimeout(() => {
      Taro.reLaunch({
        url: url
      })
    }, duration);
  }
}

let _showLoading = false

export async function showLoading(title: string, mask = true) {
  try {
    Taro.atMessage({
      'message': title,
      'type': 'info',
    })
  } catch (error) { }
  try {
    _showLoading = true
    await Taro.showLoading({
      title: title,
      mask: mask,
    })
  } catch (error) { }

  return returnObj
}

async function hideLoading() {
  if (_showLoading === true) {
    try {
      Taro.hideLoading({})
      _showLoading = false
    } catch (error) { }
  }
}

export async function showSuccess(title: string, duration = 1500) {
  await hideLoading()

  try {
    Taro.atMessage({
      'message': title,
      'type': 'success',
    })
  } catch (error) {
    try {
      await Taro.showToast({
        title: title,
        icon: 'success',
        duration: duration,
      })
    } catch (error) { }
  }
  return returnObj
}



export enum AsycnLoadingStyle {
  /** 加载 */
  LOADING,
  /** 保存 */
  SAVE,
  /** 连接 */
  CONNECT,
  /** 注册 */
  REGISTER,
  /** 刷新 */
  REFRESHING,
  /** 移除 */
  REMOVE,
  /** 中断 */
  INTERRUPT,
  /** 检查 */
  CHECK,
}



/**
 * 计算日期差
 * @param dateStart 起始日期
 * @param dateEnd 结束日期
 */
export function dateDif(dateStart: string | Date, dateEnd: string | Date) {
  const dateStart_ = new Date(dateStart).getTime()
  const dateEnd_ = new Date(dateEnd).getTime()
  const difValue = (dateEnd_ - dateStart_) / (1000 * 60 * 60 * 24)
  return difValue
}

/**
 * 将时间文本中的 '-' 转换成 '/'
 * @param date 
 */
export function dateReplace(date: string) {
  return date.replace(/-/g, '/')
}

/**
 * 分割13位数字密码
 * 000-000-000-0000
 * @param pwd 
 */
export function splitCipher(pwd: string | any) {
  if (typeof pwd !== 'string' || pwd.length < 13) return ''
  return insertStr(insertStr(insertStr(pwd, 3, '-'), 7, '-'), 11, '-')
}

function insertStr(soure: string, start: number, newStr: string) {
  return soure.slice(0, start) + newStr + soure.slice(start);
}


/** 
 * ArrayBuffer转16进度字符串示例
 * @param buffer 数据
 * @param separator 分隔符 
 */
export function ab2hex(buffer: ArrayBuffer, separator: string = ''): string {
  let hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit: { toString: (arg0: number) => string; }) {
      return ('00' + bit.toString(16)).slice(-2)
    }
  )
  return hexArr.join(separator)
}

/** ArrayBuffer转16进度字符串示例 */
export function hex2ab(hex: string): ArrayBuffer {
  const len = hex.length / 2
  const ab = new ArrayBuffer(len)
  const dv = new DataView(ab)
  for (let i = 0; i < len; i++) {
    dv.setUint8(i, parseInt(`0x${hex.slice((i * 2) + 0, (i * 2) + 2)}`))
  }
  return dv.buffer
}


/** ArrayBuffer转换为ASCII字符串 */
export function ab2Ascii(buffer: ArrayBuffer): string {
  var str = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit: number) {
      return String.fromCharCode(bit)
    }
  )
  return str.join('')
}


export function uint16ToVersion(uint16: number): string {
  let a = (uint16 & 0xFF00) >> 8
  let b = (uint16 & 0x00FF) >> 0
  return `v ${a}.${b}`
}

export function Sha1(msg: crypto.BinaryLike) {
  const sha1 = crypto.createHash('sha1');//创建哈希加密算法，后边可以是md5，sha1,sha256等
  const password = sha1.update(msg).digest();
  return ab2hex(password);
}
export function base64(msg: string) {
  
  return new Buffer(msg, 'base64').toString('hex')
}

export function sha1Base64(msg: crypto.BinaryLike) {
  const sha1 = crypto.createHash('sha1');//创建哈希加密算法，后边可以是md5，sha1,sha256等
  const password = sha1.update(msg).digest('base64');
  return password;
}

export function sha256Base64(msg: crypto.BinaryLike) {
  const sha256 = crypto.createHash('sha256');//创建哈希加密算法，后边可以是md5，sha1,sha256等
  const password = sha256.update(msg).digest('base64');
  return password;
}

export function sha512Base64(msg: crypto.BinaryLike) {
  const sha512 = crypto.createHash('sha512');//创建哈希加密算法，后边可以是md5，sha1,sha256等
  const password = sha512.update(msg).digest('base64');
  return password;
}

export function md5(msg: crypto.BinaryLike) {
  const md5 = crypto.createHash('md5');//创建哈希加密算法，后边可以是md5，sha1,sha256等
  const password = md5.update(msg).digest();
  return password;
}

/**
 * 获取ascii的ArrayBuffer
 * @param ascii ascii的字符串
 * @param len 所需的ab长度,如果undefined则返回 ascii的长度
 */
export function ascii2ab(ascii: string, len?: number | undefined): ArrayBuffer {
  const ab = new ArrayBuffer(len || ascii.length)
  const ui8 = new Uint8Array(ab)
  for (let i = 0; i < ascii.length; i++) {
    ui8[i] = ascii.charCodeAt(i)
  }
  return ui8.buffer
}

/**
* 自定义函数名：PrefixZero
* @param num： 被操作数
* @param n： 固定的总位数
* @param front： 是否在头部添加0
* @param Zero： 替换0为其他字符串
*/
export function PrefixZero(num: number | string, n: number, front: boolean = true, Zero: string = '0') {
  if (front)
    return (Array(n).join(Zero) + num).slice(-n)
  else
    return (num + Array(n).join(Zero)).slice(0, n)
}

/**
 * 获取秒级时间戳的ArrayBuffer
 * @param date 时间,默认现在
 */
export function getTimestamp2ab(date: Date = new Date()): ArrayBuffer {
  const d = parseInt((date.getTime() / 1000).toString())
  const ab = new ArrayBuffer(4)
  const dv = new DataView(ab)
  dv.setUint32(0, d, false)
  return dv.buffer
}

/**
 * 获取秒级时间戳
 * @param date 时间,默认现在
 */
export function getTimestamp(date: Date = new Date()): number {
  return parseInt((date.getTime() / 1000).toString())
}
/**
 * 延时
 * @param delay 毫秒
 */
export function delayed(delay: number) {
  return new Promise((resolve, _reject) => {
    setTimeout(() => {
      resolve()
    }, delay);
  })
}


const globalData = {}

export function setGlobalData(key: string, val: any) {
  globalData[key] = val
}

export function getGlobalData(key: string) {
  return globalData[key]
}


/**
 * randomWord 产生任意长度随机字母数字组合
 * @param randomFlag randomFlag-是否任意长度 
 * @param min min-任意长度最小位[固定位数]
 * @param max  max-任意长度最大位
 */
export function randomWord(randomFlag: boolean = true, min: number = 2, max: number = 10) {
  let str = "",
    range = min,
    arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];

  // 随机产生 
  if (randomFlag) {
    range = Math.round(Math.random() * (max - min)) + min;
  }
  for (let i = 0; i < range; i++) {
    let pos = Math.round(Math.random() * (arr.length - 1));
    str += arr[pos];
  }
  return str;
}

export function randomString(count: number) {
  return randomWord(false, count, count)
}

/**
 * randomNumberString 产生任意长度随机字母数字组合
 * @param randomFlag randomFlag-是否任意长度 
 * @param min min-任意长度最小位[固定位数]
 * @param max  max-任意长度最大位
 */
export function randomNumberString(randomFlag: boolean = true, min: number = 2, max: number = 10) {
  let str = "",
    range = min,
    arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];

  // 随机产生 
  if (randomFlag) {
    range = Math.round(Math.random() * (max - min)) + min;
  }
  for (let i = 0; i < range; i++) {
    let pos = Math.round(Math.random() * (arr.length - 1));
    str += arr[pos];
  }
  return str;
}


export function formatDate(date: string | number | Date, joinstr: string = '-') {
  const date_ = new Date(date)
  const year = date_.getFullYear()
  const month = date_.getMonth() + 1
  const day = date_.getDate()
  const hours = date_.getHours()
  const minutes = date_.getMinutes()
  const seconds = date_.getSeconds()
  function b0(num: number) {
    return num.toString().length === 1 ? `0${num}` : num
  }
  return {
    /** YYYY-M-d H:m:s */
    datetime: [year, month, day].join(joinstr) + ' ' + [hours, minutes, seconds].join(':'),
    /** YYYY-MM-dd HH:mm:ss */
    datetime2: [year, month, day].map(b0).join(joinstr) + ' ' + [hours, minutes, seconds].map(b0).join(':'),
    /** YYYY-M-d */
    date: [year, month, day].join(joinstr),
    /** YYYY-MM-dd */
    date2: [year, month, day].map(b0).join(joinstr),
    /** HH:mm:ss */
    time: [hours, minutes, seconds].join(':'),
    /** H:m:s */
    time2: [hours, minutes, seconds].map(b0).join(':'),
    /** HH:mm */
    time3: [hours, minutes].map(b0).join(':'),
    
  }
}

/**
 * 数组对象属性排序
 * arr.sort(compare('age'))
 * @param property 
 */
export function compare(property: string) {
  return function (a: any, b: any) {
    const value1 = a[property];
    const value2 = b[property];
    return value1 - value2;
  }
}


export function checkTimeSiot(timeSiot: number[]) {
  const now_ = new Date()
  const h_ = now_.getHours()
  const m_ = now_.getMinutes()
  const x_ = h_ * 60 + m_
  const start_ = timeSiot[0] * 60 + timeSiot[1]
  const end_ = timeSiot[2] * 60 + timeSiot[3]
  console.log({
    start_,
    x_,
    end_
  });

  return start_ <= x_ && x_ <= end_
}

export function checkUsagePeriod(start: Date, end: Date) {
  const now_ = new Date().getTime()
  const start_ = start.getTime()
  const end_ = end.getTime()
  return start_ <= now_ && now_ <= end_
}

export function getUserNunberKey(date_: Date) {
  const year = date_.getFullYear()
  const month = date_.getMonth() + 1
  const day = date_.getDate()
  const hours = date_.getHours()
  const minutes = date_.getMinutes()
  const datetime = [year, month, day].map(x => PrefixZero(x, 2)).join('') + [hours, minutes].map(x => PrefixZero(x, 2)).join('')
  return datetime
}


const funcLock = {}
/**
 * 检查函数锁，避免出现联系点击导致的错误
 * @param name 函数名称
 * @returns 如果上锁了,返回真,否则返回假
 */
export function checkFuncLock(name: string) {
  return funcLock[name] || false
}
/**
 * 函数锁上锁,默认300毫秒后自动解锁
 * @param name 
 */
export function onFuncLock(name: string, autoOff = 800) {
  funcLock[name] = true
  setTimeout(() => {
    offFuncLock(name)
  }, autoOff);
}
/**
 * 函数锁解锁
 * @param name 
 */
export function offFuncLock(name: string) {
  funcLock[name] = false
}


/** 首先将字符串转为16进制 */
export function string2buffer(str: string) {
  let val = ""
  for (let i = 0; i < str.length; i++) {
    if (val === '') {
      val = str.charCodeAt(i).toString(16)
    } else {
      val += ',' + str.charCodeAt(i).toString(16)
    }
  }
  // 将16进制转化为ArrayBuffer
  return new Uint8Array((val.match(/[\da-f]{2}/gi) || []).map(function (h) {
    return parseInt(h, 16)
  })).buffer
}



export function HmacSHA256(msg: crypto.BinaryLike, key: crypto.BinaryLike | crypto.KeyObject) {
  const sha256 = crypto.createHmac('sha256', key);//创建哈希加密算法，后边可以是md5，sha1,sha256等
  const password = sha256.update(msg).digest('hex');
  return password;
}

/** 压缩(string->gzip->base64) */
export function strGzip2base64(str: string): Promise<string> {
  return new Promise((resolve, reject) => {
    zlib.gzip(str, function (err, buf) {
      if (!err) {
        resolve(buf.toString('base64'))
      } else {
        reject(err)
      }
    })
  })
}
/** 解压缩(base64->gunzip->string) */
export function base64Gunzip2str(str: string): Promise<string> {
  return new Promise((resolve, reject) => {
    const buf = Buffer.from(str, 'base64')
    zlib.gunzip(buf, function (err, buffer) {
      if (err) {
        reject(err)
      } else {
        const c = buffer.toString('utf-8')
        resolve(c)
      }
    })
  })
}


/**
 * 注释：E是计算表达式，S是需要乘以10的多少次方
 * countFloat(10.5452,2) = 10.54
 * @param E 浮点数
 * @param S 保留的小数位数
 */
export function countFloat(E: number, S: number) {

  let n = Math.pow(10, S);

  let res = Math.round(E * n) / n;

  return res;

}


export function toThousands(num: number | string) {
  let s = (num || 0).toString()
  let a = s.split('.')
  if (a.length > 0) {
    return a[0].replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') + '.' + a[1]
  } else {
    return s.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')
  }
}